package com.upay.android.controller.fragment;

import static com.upay.android.controller.helper.Format.format;

import java.math.BigDecimal;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;

import com.upay.android.R;
import com.upay.android.controller.policy.ResultMappingPolicy;
import com.upay.android.domain.user.UserWrapper;

public class TransactionCalculatorFragment<T extends ResultMappingPolicy> extends AbstractFragment
	implements OnClickListener {

	/* ---- Constants ---- */
    // operator types
    public static final String ADD = "+";
    public static final String DECIMALPOINT = ".";
    public static final String CLEAR = "C";
    public static final String OK = "OK";
    public static final String EQUALS = "=";
    
    public static final int MAX_NUMBER_INTEGER_DIGITS = 5;
    public static final int MAX_NUMBER_DECIMAL_DIGITS = 2;

	/* ---- Instance Variables ---- */
	private BigDecimal number = null;
	private BigDecimal result = null;
	private BigDecimal scale = null;
	private BigDecimal intermediateResult = null;
	private int integerDigits = 0;
	private int decimalDigits = 0;
	private Boolean hasDecimalPointSet = false;
	private TextView mDisplay = null;
	private T resultMappingPolicy = null;

	/* ---- Business Methods ---- */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setHasOptionsMenu(true);
	}
		

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_fixed_payment_transaction_detail, parent, false);
        TextView textView = (TextView)view.findViewById(R.id.fullname);
        textView.setText(UserWrapper.getFullName(resultMappingPolicy.getUser()));
        
        view.findViewById(R.id.buttonZero).setOnClickListener(this);
        view.findViewById(R.id.buttonOne).setOnClickListener(this);
        view.findViewById(R.id.buttonTwo).setOnClickListener(this);
        view.findViewById(R.id.buttonThree).setOnClickListener(this);
        view.findViewById(R.id.buttonFour).setOnClickListener(this);
        view.findViewById(R.id.buttonFive).setOnClickListener(this);
        view.findViewById(R.id.buttonSix).setOnClickListener(this);
        view.findViewById(R.id.buttonSeven).setOnClickListener(this);
        view.findViewById(R.id.buttonEight).setOnClickListener(this);
        view.findViewById(R.id.buttonNine).setOnClickListener(this);
        view.findViewById(R.id.buttonPlus).setOnClickListener(this);
        view.findViewById(R.id.buttonEquals).setOnClickListener(this);
        view.findViewById(R.id.buttonClean).setOnClickListener(this);
        view.findViewById(R.id.buttonOK).setOnClickListener(this);
        view.findViewById(R.id.buttonDecimalPoint).setOnClickListener(this);
        
        mDisplay = (TextView)view.findViewById(R.id.displayvalue);
        cleanResult();
        return view; 
    }
	
        
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
    	switch(item.getItemId()) {
    	case android.R.id.home:
    		getFragmentManager().popBackStack();
    	default:
    		return super.onOptionsItemSelected(item);

    	}
    }

	@Override
	public void onClick(View view) {
		String buttonPressed = ((Button) view).getText().toString();
		
		if (Character.isDigit(buttonPressed.charAt(0))) {
			// digit
			if (hasDecimalPointSet) {
				if (decimalDigits++ < MAX_NUMBER_DECIMAL_DIGITS) {
					scale = scale.multiply(new BigDecimal(10));
					number = (number.add((new BigDecimal(buttonPressed)).divide(scale)));
				}
			} else {
				// no decimal point set
				if (integerDigits++ < MAX_NUMBER_INTEGER_DIGITS) {
					number = (number.multiply(new  BigDecimal(10)).add((new BigDecimal(buttonPressed)).divide(scale)));
				}
			}
			displayResult(number);
		} else {
			// operation
			if (DECIMALPOINT.equals(buttonPressed)) {
				hasDecimalPointSet = Boolean.TRUE;
			} else {
				if (CLEAR.equals(buttonPressed)) {
					cleanResult();
				} else {
					if (ADD.equals(buttonPressed)) {
						intermediateResult = intermediateResult.add(number);
						cleanDecimalEntry();
					} else {
						if (EQUALS.equals(buttonPressed)) {
							intermediateResult = intermediateResult.add(number);
							cleanDecimalEntry();
						} else {
							if (OK.equals(buttonPressed)) {
								result = intermediateResult.add(number);
								resultMappingPolicy.mapResult(result);
								getFragmentManager().popBackStack();
							}
						}
					}
				}
				displayResult(intermediateResult);
			}	
			
		} // is digit
	}
	
	private void cleanDecimalEntry() {
		number = new BigDecimal(0);
		scale = new BigDecimal(1);
		integerDigits = 0;
		decimalDigits = 0;
		hasDecimalPointSet = Boolean.FALSE;		
	}
	
	private void cleanResult() {
		number = new BigDecimal(0);
		result = new BigDecimal(0);
		scale = new BigDecimal(1);
		integerDigits = 0;
		decimalDigits = 0;
		intermediateResult = new BigDecimal(0);
		hasDecimalPointSet = Boolean.FALSE;
		displayResult(intermediateResult);	
	}
	
	private void displayResult(BigDecimal decimal) {
		mDisplay.setText(format(decimal));
	}

	/* ---- Getters and Setters ---- */

	public T getResultMappingPolicy() {
		return resultMappingPolicy;
	}


	public void setResultMappingPolicy(T resultMappingPolicy) {
		this.resultMappingPolicy = resultMappingPolicy;
	}

}

